/**
 *	\file AKTTTGeometryProvider.m
 *  
 *  \section desc_sec Description
 *  Description
 *  
 *  \if copyright
 *  	Copyright 2008 Ben Chen. All rights reserved.
 *  \endif
 *  
 *  \section hist_sec Change History:
 *  	-	1/13/08		BC		Created this file
 *  
 *  <hr>
 *  \addtogroup AnimalKingdom
 *	@{
 */

#import "AKTTT.h"
#import "AKTTTGeometryProvider.h"

@implementation AKTTTGeometryProvider

- (id) init
{
	self = [super init];
	
	if (self != nil) 
	{
		chessboardSize = NSMakeSize(571, 512); //NSMakeSize(1024, 670.0);
		
		[self getCellPositions:cellRects
					   forRect:NSMakeRect(15, 17, 550, 480)//NSMakeRect(237, 80, 565, 475)
				  topRowLength:485
					 numOfRows:3 
				  numOfColumns:3];
	}
	
	return self;
}

- (NSSize)chessboardSize
{
	return chessboardSize;
}

inline float heightForWidth(float width, float bottomWidth, float rateOfSlope)
{
	return (bottomWidth - width) / rateOfSlope;
}

- (BOOL)getCellPositions:(NSRect [][3])newCellRects
				 forRect:(NSRect)chessboardRect 
			topRowLength:(float)topWidth
			   numOfRows:(unsigned)numOfRows 
			numOfColumns:(unsigned)numOfCols
{
	/*
			 |------------------------------------|
			 |                                    |
			 |         /<-  topWidth  ->\         |------
			 |        /                  \        |  /\
			 |       /                    \       |  ||
			 |      /                      \      | height
			 |     /                        \     |  ||
	         |    /                          \    |  \/
			 |   /<-       bottomWidth      ->\   |------
			 |                                    | bottomMargin
			 |------------------------------------|------	 
		   ->|  |<-
		  leftMargin
	 */
	
	BOOL retVal;
	
	if (numOfRows > 0 && numOfCols > 0)
	{
		float bottomWidth = NSWidth(chessboardRect); 
		float height      = NSHeight(chessboardRect);
		
		float bottomMargin	= chessboardRect.origin.y;
		float leftMargin	= chessboardRect.origin.x;
		
		// Calculate the ratio between lengths of two adjacent horizontal lines
		float rowRatio = pow(topWidth/bottomWidth, 1.0/numOfRows);
		
		// Use this value to calculate height later
		float rateOfSlope = (bottomWidth - topWidth) / height;
		
		float marginTopLeft = (bottomWidth - topWidth) / 2;
		int i, j;
		float marginRowLeft, cellWidth;

		float floorWidth = bottomWidth;
		float ceilingWidth = floorWidth * rowRatio;
	
		float floorHeight = heightForWidth(floorWidth, bottomWidth, rateOfSlope);
		float ceilingHeight = heightForWidth(ceilingWidth, bottomWidth, rateOfSlope);
		// Calculate from bottom to top
		for (i = 0; i < numOfRows; ++i) 
		{
			
			marginRowLeft	= (floorHeight + ceilingHeight) / 2 * marginTopLeft / height; 
			cellWidth		= (bottomWidth - marginRowLeft*2) / numOfCols;
			
			for (j = 0; j < numOfCols; ++j) 
			{
				newCellRects[i][j].origin.x = marginRowLeft + cellWidth*j + leftMargin;
				newCellRects[i][j].origin.y = floorHeight + bottomMargin;
				newCellRects[i][j].size.width = newCellRects[i][j].size.height = (ceilingHeight - floorHeight);
			}
			
			floorWidth = ceilingWidth;
			ceilingWidth *= rowRatio;
			floorHeight = ceilingHeight;
			ceilingHeight = heightForWidth(ceilingWidth, bottomWidth, rateOfSlope);
		}
		
		retVal = YES;
	}
	else
		retVal = NO;
	
	return retVal;	
}

- (NSRect)rectForCell:(AKCellIndex)cellIndex
{
	NSRect retVal;
	
	if (cellIndex >= 0 && cellIndex <= 8)
	{
		unsigned col = cellIndex % 3;
		unsigned row = cellIndex / 3;
		
		retVal = cellRects[row][col];
	}
	else
		retVal = NSZeroRect;
	
	return retVal;
}

@end

/** @} */